package eiisan.crypto.demo.duichen;

import org.apache.commons.codec.binary.Hex;
import org.bouncycastle.jce.provider.BouncyCastleProvider;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;

public class DesSemo {

    public static void main(String[] args) {
        //jdkDES加密: cfa7121606a4413138d8d3781afeaa1c
        try {

            SecretKey key = getSecretKey("aaaabbbbcc");
            byte[] content = jdkDESEncrypt("Hello DES", key);
            jdkDESDecrypt(content, key);

            bcDES();

        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
    }

    public static SecretKey getDefaultSecretKey() {
        KeyGenerator keyGenerator = null;
        SecretKey secretKey = null;
        try {
            keyGenerator = KeyGenerator.getInstance("DES");
            keyGenerator.init(56);      //指定key长度，同时也是密钥长度(56位)
            secretKey = keyGenerator.generateKey(); //生成key的材料
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return secretKey;
    }

    /**
     * key 长度 > 8
     *
     * @param key
     * @return
     * @throws InvalidKeyException
     */
    public static SecretKey getSecretKey(String key) throws InvalidKeyException {
        SecretKey secretKey = null;

        byte[] keyByteArr = key.getBytes();

        if (keyByteArr.length - 0 < 8) {
            throw new InvalidKeyException("Wrong key size");
        }

        DESKeySpec desKeySpec = null;
        try {
            desKeySpec = new DESKeySpec(keyByteArr);
            SecretKeyFactory factory = SecretKeyFactory.getInstance("DES");
            secretKey = factory.generateSecret(desKeySpec);
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (InvalidKeySpecException e) {
            e.printStackTrace();
        }

        return secretKey;
    }

    /**
     * DES 加密
     *
     * @param content
     * @param key2
     */
    public static byte[] jdkDESEncrypt(String content, SecretKey key2) {
        //加密
        Cipher cipher = null;

        byte[] result = null;
        try {
            //算法类型/工作方式/填充方式
            cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            //指定为加密模式
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            result = cipher.doFinal(content.getBytes());

            //转换为十六进制
            //desResult = Hex.encodeHexString(result);

        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 解密
     *
     * @param encrypt
     * @param key
     */
    public static void jdkDESDecrypt(byte[] encrypt, SecretKey key) {
        Cipher cipher = null;
        try {
            cipher = Cipher.getInstance("DES/ECB/PKCS5Padding");
            //解密
            cipher.init(Cipher.DECRYPT_MODE, key);  //相同密钥，指定为解密模式
            byte[] result = cipher.doFinal(encrypt);   //根据加密内容解密
            System.out.println("jdkDES解密: " + new String(result));  //转换字符串
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
        } catch (BadPaddingException e) {
            e.printStackTrace();
        } catch (IllegalBlockSizeException e) {
            e.printStackTrace();
        } catch (InvalidKeyException e) {
            e.printStackTrace();
        }

    }

    /**
     * BC方式
     */
    public static void bcDES(){
        String src = "Hello DES";
        try {
            //通过改变provider的方式
            Security.addProvider(new BouncyCastleProvider());

            //生成key,使用bc需要在后面指定"BC"
            KeyGenerator keyGenerator=KeyGenerator.getInstance("DES","BC");

            keyGenerator.getProvider();

            keyGenerator.init(56);      //指定key长度，同时也是密钥长度
            SecretKey secretKey = keyGenerator.generateKey(); //生成key的材料
            byte[] key = secretKey.getEncoded();  //生成key

            //key转换成密钥
            DESKeySpec desKeySpec=new DESKeySpec(key);
            SecretKeyFactory factory=SecretKeyFactory.getInstance("DES");
            SecretKey key2 = factory.generateSecret(desKeySpec);      //转换后的密钥

            //加密
            Cipher cipher=Cipher.getInstance("DES/ECB/PKCS5Padding");  //算法类型/工作方式/填充方式
            cipher.init(Cipher.ENCRYPT_MODE, key2);
            byte[] result=cipher.doFinal(src.getBytes());
            System.out.println("bcDES加密: "+ Hex.encodeHexString(result));  //转换为十六进制

            //解密
            cipher.init(Cipher.DECRYPT_MODE,key2);  //相同密钥
            result = cipher.doFinal(result);   //根据加密内容解密
            System.out.println("bcDES解密: "+new String(result));  //转换字符串

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}